package network.handlers;

import static org.junit.Assert.*;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

import managers.ElevatorManager;
import managers.HallCallManager;
import messages.BaseMessage;
import messages.DeregistrationMessage;
import messages.MessageFactory;
import messages.MessageType;
import messages.elevator.ElevatorStatusRequest;
import messages.registration.ElevatorRegistrationMessage;
import messages.registration.ObserverRegistrationMessage;
import network.managers.ObserverManager;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import test.BaseTest;

public class ElevatorModeHandlerTest extends BaseTest {

    private Socket sock;
    
    @BeforeClass
    public static void initSystem() throws IOException
    {
        BaseTest.initSystem();
        
        //shut down the other threads, so that only the registration threads are running
        HallCallManager.shutdown();
        ElevatorManager.shutdown();
        ObserverManager.shutdown();
    }
    
    @AfterClass
    public static void teardownSystem() throws IOException
    {
        BaseTest.teardownSystem();
    }
    
    @Before
    public void setup() throws IOException
    {
        sock = new Socket(InetAddress.getLocalHost(), port);
        
        ElevatorRegistrationMessage mess = new ElevatorRegistrationMessage((byte) 0);
        sock.getOutputStream().write(mess.toByteArray());
        
        BaseMessage recv = MessageFactory.readMessage(sock);
        assertEquals(MessageType.ElevatorRegistrationMessageAck, recv.getMessageType());
    }
    
    @After
    public void cleanUp()
    {
        if (sock != null)
        {
            try
            {
                sock.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    
    @Test
    public void testDeregistration() throws IOException
    {
        DeregistrationMessage deReg = new DeregistrationMessage();
        sock.getOutputStream().write(deReg.toByteArray());
        
        BaseMessage recv = MessageFactory.readMessage(sock);
        assertEquals(MessageType.DeregistrationMessage, recv.getMessageType());
    }
    
    @Test
    public void testInvalidMessage() throws IOException, InterruptedException
    {
        ObserverRegistrationMessage req = new ObserverRegistrationMessage();
        sock.getOutputStream().write(req.toByteArray());
        Thread.sleep(100);
        
        ElevatorStatusRequest req2 = new ElevatorStatusRequest();
        sock.getOutputStream().write(req2.toByteArray());
        Thread.sleep(100);
        
        sock.getOutputStream().write(req2.toByteArray());
        
        BaseMessage recv = MessageFactory.readMessage(sock);
        assertEquals(MessageType.DeregistrationMessage, recv.getMessageType());
    }
    
    @Test
    public void testNonMessage() throws IOException, InterruptedException
    {
        byte[] message1 = new byte[] {0x11};
        sock.getOutputStream().write(message1);
        Thread.sleep(100);
        byte[] message2 = new byte[] {0x12};
        sock.getOutputStream().write(message2);
        Thread.sleep(100);
        byte[] message3 = new byte[] {0x13};
        sock.getOutputStream().write(message3);
        
        BaseMessage recv = MessageFactory.readMessage(sock);
        assertEquals(MessageType.DeregistrationMessage, recv.getMessageType());
    }

}
